home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 24 / AACD 24.iso / AACD / System / ReqToolsLib / Source / reqtools / req.c < prev    next >
Encoding:
C/C++ Source or Header  |  2001-07-02  |  30.3 KB  |  1,014 lines

  1.  
  2. #include <exec/types.h>
  3. #include <exec/io.h>
  4. #include <exec/memory.h>
  5. #include <intuition/intuition.h>
  6. #include <intuition/intuitionbase.h>
  7. #include <intuition/sghooks.h>
  8. #include <intuition/imageclass.h>
  9. #include <libraries/dos.h>
  10. #include <libraries/gadtools.h>
  11. #include <libraries/reqtools.h>
  12. #include <proto/exec.h>
  13. #include <proto/gadtools.h>
  14. #include <proto/graphics.h>
  15. #include <proto/intuition.h>
  16. #include <proto/utility.h>
  17. #include <proto/reqtools.h>
  18. #include <string.h>
  19.  
  20. #include "filereq.h"
  21.  
  22.  
  23. #include "rtlocale.h"
  24.  
  25. /****************************************************************************************/
  26.  
  27. #ifndef _AROS
  28.  
  29. #ifdef __SASC
  30. #pragma libcall ReqToolsBase rtLockPrefs a8 00
  31. #pragma libcall ReqToolsBase rtUnlockPrefs ae 00
  32. #else
  33. #warning You might have to fix rtLockPrefs/rtUnlockPrefs for your compiler
  34. #endif
  35.  
  36. #endif
  37.  
  38. /****************************************************************************************/
  39.  
  40. #define ThisProcess()    ( ( struct Process * ) FindTask( NULL ) )
  41.  
  42. /****************************************************************************************/
  43.  
  44. struct PWCallBackArgs
  45. {
  46.     char     *buffer;
  47.     ULONG     lastchecksum, verify, retcode;
  48. };
  49.  
  50. /****************************************************************************************/
  51.  
  52. extern ULONG ASM LoopReqHandler (ASM_REGPARAM(a1, struct rtHandlerInfo *,));
  53. extern void REGARGS SetWinTitleFlash (struct Window *, char *);
  54. extern void ShortDelay (void);
  55. extern ULONG ASM myTextLength (ASM_REGPARAM(a1, char *,),
  56.                            ASM_REGPARAM(a0, struct TextAttr *,),
  57.                    ASM_REGPARAM(a3, UBYTE *,),
  58.                    ASM_REGPARAM(a2, struct Image *,),
  59.                    ASM_REGPARAM(d7, ULONG,));
  60.  
  61. extern struct ReqToolsBase *ReqToolsBase;
  62. extern struct DosLibrary *DOSBase;
  63. extern struct IntuitionBase *IntuitionBase;
  64. extern struct Library *GadToolsBase;
  65. extern struct GfxBase *GfxBase;
  66.  
  67. /****************************************************************************************/
  68.  
  69. struct FmtBuff
  70. {
  71.     long numlines, bufflen;
  72. };
  73.  
  74. #define DOFMT_COUNTNEWLINES        0
  75. #define DOFMT_COUNTBARS            1
  76.  
  77. /****************************************************************************************/
  78.  
  79.  
  80. extern APTR ASM DofmtCount (ASM_REGPARAM(a0, char *,),
  81.                             ASM_REGPARAM(a1, APTR,),
  82.                 ASM_REGPARAM(a3, struct FmtBuff *,),
  83.                 ASM_REGPARAM(d0, int,));
  84. extern APTR STDARGS DofmtArgs (char *, char *,...);
  85.  
  86.  
  87. extern void ASM FillBarTable (ASM_REGPARAM(a1, char **,), ASM_REGPARAM(a0, char *,));
  88. extern void ASM FillNewLineTable (ASM_REGPARAM(a1, char **,), ASM_REGPARAM(a0, char *,));
  89.  
  90. /****************************************************************************************/
  91.  
  92. typedef struct Req_RealHandlerInfo    Req_GlobData;
  93. #define STRINGGADID            32
  94.  
  95. struct Req_RealHandlerInfo
  96. {
  97.     ULONG             (*func)();        /* private */
  98.     ULONG             WaitMask;
  99.     ULONG             DoNotWait;
  100.  
  101.     /* PRIVATE */
  102.     char             **gadstrbuff, **buff, *stringbuff, *textfmt;
  103.     struct PWCallBackArgs     arg;
  104.     struct Gadget         *strgad, *yesgad, *nogad, *retgad, *selgad;
  105.     struct TextAttr         boldattr;
  106.     struct KeyButtonInfo     buttoninfo;
  107.     struct StringInfo         *strinfo;
  108.     struct Screen         *scr, *frontscr;
  109.     struct Window         *prwin;
  110.     struct Window         *reqwin;
  111.     struct DrawInfo         *drinfo;
  112.     struct rtReqInfo         *reqinfo;
  113.     struct Hook         *imsghook, backfillhook;
  114.     struct TextFont         *reqfont;
  115.     struct Catalog         *catalog;
  116.     struct Image         headimg;
  117.     struct NewWindow         newreqwin;
  118.     struct FmtBuff         bodyfmt, gadfmtbuff;
  119.     UBYTE             minmaxstr[30];
  120.     int             idcmp, mode, min, max, checksum, pubscr, reqflags;
  121.     int             retnum, waitpointer, allowempty, lockwindow, shareidcmp, noscreenpop;
  122.     int             textht, texttop, strgadht, strgadtop, width, nowinbackfill;
  123.     int             numlines, len, fontht, minmax, minmaxlen, minmaxtop, minmaxleft;
  124.     int             fkeys;
  125.     APTR             winlock, visinfo;
  126.     ULONG             *value, *lenptr;
  127. };
  128.  
  129. /****************************************************************************************/
  130.  
  131. static UWORD pattern[] = { 0xAAAA,0x5555 };
  132.  
  133. static ULONG REGARGS ReqExit (Req_GlobData *, int);
  134. static struct Image * REGARGS CreateRectImage
  135.             (Req_GlobData *, struct Image *, int, int, int, int, int, int);
  136. static ULONG ASM SAVEDS myReqHandler (REGPARAM(a1, Req_GlobData *,),
  137.                           REGPARAM(d0, ULONG,),
  138.                       REGPARAM(a0, struct TagItem *,));
  139.  
  140. /****************************************************************************************/
  141.  
  142. #define GETSTRINGLONG_FLAGS    (GSREQF_CENTERTEXT|GSREQF_HIGHLIGHTTEXT)
  143. #define EZREQ_FLAGS        (EZREQF_NORETURNKEY|EZREQF_LAMIGAQUAL|EZREQF_CENTERTEXT)
  144.  
  145.  
  146. /****************************************************************************************/
  147.  
  148. ULONG ASM SAVEDS GetString (
  149.     REGPARAM(a1, UBYTE *, stringbuff),        /* str in case of rtEZRequestA */
  150.     REGPARAM(d0, LONG, maxlen),            /* args in case of rtEZRequestA */
  151.     REGPARAM(a2, char *, title),            /* gadfmt in case of rtEZRequestA */
  152.     REGPARAM(d1, ULONG, checksum),
  153.     REGPARAM(d2, ULONG *, value),
  154.     REGPARAM(d3, LONG, mode),
  155.     REGPARAM(d4, struct rtReqInfo *, reqinfo),
  156.     REGPARAM(a0, struct TagItem *, taglist))
  157. {
  158. /* #define CLEARSIZE    (28+sizeof(struct NewWindow)+sizeof(struct IntuiText)+\
  159.                  sizeof(struct NewGadget)+2*sizeof(struct FmtBuff)) */
  160.                  
  161.     /* keep these vars together and just BEFORE NewWindow struct! */
  162.     /*-------------------------------------------------*/
  163.     int         reqpos = REQPOS_DEFAULT;
  164.     char         *pubname = NULL;
  165.     ULONG         underscore = 0;
  166.     struct TextAttr     *fontattr = NULL;
  167.     struct Locale     *locale = NULL;
  168.     struct IntuiText     itxt, *bodyitxt = NULL;
  169.     struct NewGadget     ng;
  170.     struct Image     *img;
  171.     /**/
  172.     /* KEEP MIN AND MAX IN THIS ORDER !!!! */
  173.     int         max = MAXINT, min = MININT;
  174.     /**/
  175.     Req_GlobData    *glob;
  176.     struct Gadget     *gad;
  177.     struct TagItem     *tag, *tstate;
  178.     /* for rtEZRequestA */
  179.     char         *gadfmt = title;
  180.     char         *ptr;
  181.     int         val, spacing, reqhandler = FALSE, nogadfmt, gadlen = 0;
  182.     int         height, top, showdef = TRUE;
  183.     int         scrwidth, scrheight, i, j, npos, nlen, nogadgets, retnum;
  184.     int         invisible, scrfontht, gadlines = 0;
  185.     int         leftoff, rightoff;
  186.     ULONG         tagdata, *gadlenptr, *gadposptr, idcmpflags;
  187.     APTR         gadfmtargs, textfmtargs, args;
  188.  
  189.     memset (&itxt, 0, sizeof (struct IntuiText));
  190.     memset (&ng, 0, sizeof (struct NewGadget));
  191.  
  192.     if (!(glob = AllocVec (sizeof (Req_GlobData), MEMF_PUBLIC | MEMF_CLEAR)))
  193.     return (FALSE);
  194.         
  195.     glob->mode = mode;
  196.     glob->checksum = checksum;
  197.     glob->value = value;
  198.     glob->stringbuff = stringbuff;
  199.     glob->fkeys = rtLockPrefs()->Flags & RTPRF_FKEYS;
  200.     rtUnlockPrefs();
  201.  
  202.     nogadfmt = (mode != IS_EZREQUEST);
  203.     invisible = (mode <= ENTER_PASSWORD);
  204.  
  205.     if (mode == IS_EZREQUEST) title = NULL;
  206.     if (mode == ENTER_STRING) glob->width = 350; else glob->width = 180;
  207.     retnum = 1;
  208.     if ((glob->reqinfo = reqinfo))
  209.     {
  210.     if (reqinfo->Width) glob->width = reqinfo->Width;
  211.     if (reqinfo->ReqTitle) title = reqinfo->ReqTitle;
  212.     if (reqinfo->ReqPos != REQPOS_DEFAULT) reqpos = reqinfo->ReqPos;
  213.     
  214.     glob->newreqwin.LeftEdge = reqinfo->LeftOffset;
  215.     glob->newreqwin.TopEdge = reqinfo->TopOffset;
  216.     glob->reqflags = reqinfo->Flags;
  217.     glob->waitpointer = reqinfo->WaitPointer;
  218.     glob->lockwindow = reqinfo->LockWindow;
  219.     glob->shareidcmp = reqinfo->ShareIDCMP;
  220.     glob->imsghook = reqinfo->IntuiMsgFunc;
  221.     }
  222.         
  223.     /* parse tags */
  224.     tstate = taglist;
  225.     while ((tag = NextTagItem ((const struct TagItem **)&tstate)))
  226.     {
  227.     tagdata = tag->ti_Data;
  228.     if (tag->ti_Tag > RT_TagBase)
  229.     {
  230.         switch (tag->ti_Tag)
  231.         {
  232.         case RT_Window:            glob->prwin = (struct Window *)tagdata; break;
  233.         case RT_IDCMPFlags:        glob->idcmp = tagdata; break;
  234.         case RT_ReqPos:            reqpos = tagdata; break;
  235.         case RT_LeftOffset:        glob->newreqwin.LeftEdge = tagdata; break;
  236.         case RT_TopOffset:        glob->newreqwin.TopEdge = tagdata; break;
  237.         case RT_PubScrName:        pubname = (char *)tagdata; break;
  238.         case RT_Screen:            glob->scr = (struct Screen *)tagdata; break;
  239.         case RT_ReqHandler:        *(APTR *)tagdata = glob;
  240.                                         reqhandler = TRUE;
  241.                                         break;
  242.         case RT_WaitPointer:        glob->waitpointer = tagdata; break;
  243.         case RT_Underscore:        underscore = tagdata; break;
  244.         case RT_ShareIDCMP:        glob->shareidcmp = tagdata; break;
  245.         case RT_LockWindow:        glob->lockwindow = tagdata; break;
  246.         case RT_ScreenToFront:        glob->noscreenpop = !tagdata; break;
  247.         case RT_TextAttr:            fontattr = (struct TextAttr *)tagdata; break;
  248.         case RT_IntuiMsgFunc:        glob->imsghook = (struct Hook *)tagdata; break;
  249.         case RT_Locale:            locale = (struct Locale *)tagdata; break;
  250.         case RTEZ_ReqTitle:        if (mode == IS_EZREQUEST) title = (char *)tagdata;
  251.                                         break;
  252.         /* RTGS_Flags == RTGL_Flags == RTEZ_Flags */
  253.         case RTEZ_Flags:        glob->reqflags = tagdata; break;
  254.         case RTEZ_DefaultResponse:     retnum = tagdata; break;
  255.         case RTGL_Min:            min = tagdata; glob->minmax = TRUE; break;
  256.         case RTGL_Max:            max = tagdata; glob->minmax = TRUE; break;
  257.         /* RTGS_Width == RTGL_Width */
  258.         case RTGL_Width:        if (mode == ENTER_NUMBER || mode == ENTER_STRING)
  259.                                             glob->width = tagdata;
  260.                                         break;
  261.         case RTGL_ShowDefault:    showdef = tagdata; break;
  262.         /* RTGS_GadFmt == RTGL_GadFmt */
  263.         case RTGL_GadFmt:        nogadfmt = FALSE;
  264.                         gadfmt = (char *)tagdata;
  265.                         break;
  266.         /* RTGS_GadFmtArgs == RTGL_GadFmtArgs */
  267.         case RTGL_GadFmtArgs:       gadfmtargs = (APTR)tagdata; break;
  268.         /* RTGS_Invisible == RTGL_Invisible */
  269.         case RTGL_Invisible:        invisible = tagdata; break;
  270.         /* RTGS_BackFill == RTGL_BackFill */
  271.         case RTGL_BackFill:        if (mode == ENTER_NUMBER || mode == ENTER_STRING)
  272.                             glob->nowinbackfill = !tagdata;
  273.                             break;
  274.         /* RTGS_TextFmt == RTGL_TextFmt */
  275.         case RTGL_TextFmt:        if (mode == ENTER_NUMBER || mode == ENTER_STRING)
  276.                             glob->textfmt = (char *)tagdata;
  277.                             break;
  278.         /* RTGS_TextFmtArgs == RTGL_TextFmtArgs */
  279.         case RTGL_TextFmtArgs:        textfmtargs = (APTR)tagdata; break;
  280.         case RTGS_AllowEmpty:        glob->allowempty = tagdata; break;
  281.         
  282.         } /* switch (tag->ti_Tag) */
  283.         
  284.     } /* if (tag->ti_Tag > RT_TagBase)*/
  285.     
  286.     } /* while ((tag = NextTagItem ((const struct TagItem **)&tstate))) */
  287.  
  288.     glob->catalog = RT_OpenCatalog (locale);
  289.  
  290.     /* ignore RTGL_Min and RTGL_Max if not rtNewGetLongA() */
  291.     if (mode != ENTER_NUMBER) glob->minmax = FALSE;
  292.     retnum++;
  293.     glob->newreqwin.Flags = WFLG_DEPTHGADGET|WFLG_DRAGBAR|WFLG_ACTIVATE
  294.                 |WFLG_SIMPLE_REFRESH|WFLG_RMBTRAP;
  295.  
  296.     idcmpflags = glob->idcmp | IDCMP_REFRESHWINDOW|IDCMP_GADGETUP|IDCMP_RAWKEY;
  297.     if (mode != IS_EZREQUEST) idcmpflags |= IDCMP_MOUSEBUTTONS|IDCMP_ACTIVEWINDOW;
  298.  
  299.     if (!glob->prwin || !glob->prwin->UserPort
  300.              || (glob->prwin->UserPort->mp_SigTask != ThisProcess()))
  301.     glob->shareidcmp = FALSE;
  302.  
  303.     if (!(glob->scr = GetReqScreen (&glob->newreqwin, &glob->prwin, glob->scr, pubname)))
  304.     return (ReqExit (glob, FALSE));
  305.     
  306.     spacing = rtGetVScreenSize (glob->scr, (ULONG *)&scrwidth, (ULONG *)&scrheight);
  307.  
  308.     if (fontattr)
  309.     {
  310.     if (!(glob->reqfont = OpenFont (fontattr))) fontattr = NULL;
  311.     }
  312.     
  313.     if (!fontattr) fontattr = glob->scr->Font;
  314.  
  315.     if (!(glob->visinfo = GetVisualInfoA (glob->scr, NULL))
  316.     || !(glob->drinfo = GetScreenDrawInfo (glob->scr)))
  317.     return (ReqExit (glob, FALSE));
  318.  
  319.     itxt.ITextFont = fontattr;
  320.     glob->boldattr = *fontattr;
  321.     glob->boldattr.ta_Style |= FSF_BOLD;
  322.     glob->fontht = fontattr->ta_YSize;
  323.     scrfontht = glob->scr->Font->ta_YSize;
  324.     leftoff = glob->scr->WBorLeft + 4;
  325.     rightoff = glob->scr->WBorRight + 4;
  326.  
  327.     /* Calculate the width, height and position of the requester window. We try
  328.         to position the window as close to the mouse as possible (default). */
  329.  
  330.     if (mode != IS_EZREQUEST)
  331.     {
  332.     if (nogadfmt)
  333.     {
  334.         underscore = '_';
  335.         gadfmt = GetStr (glob->catalog, MSG_OK_BAR_CANCEL);
  336.         if (mode <= ENTER_PASSWORD)
  337.         {
  338.         gadfmt = GetStr (glob->catalog, MSG_LAST_BAR_CANCEL);
  339.         if (!stringbuff[0] || mode == CHECK_PASSWORD)
  340.             while (*gadfmt && (*gadfmt++ != '|'));
  341.         }
  342.     }
  343.     glob->reqflags &= GETSTRINGLONG_FLAGS;
  344.     glob->reqflags |= EZREQF_NORETURNKEY;
  345.     }
  346.     else
  347.     {
  348.     glob->reqflags &= EZREQ_FLAGS;
  349.     glob->textfmt = stringbuff;
  350.     textfmtargs = (APTR)maxlen;
  351.     }
  352.  
  353.     if (glob->textfmt)
  354.     {
  355.     /* Calculate size of buffer needed to expand format string, also
  356.         calculates number of lines in format string.
  357.         (APTR)maxlen points to the arguments! */
  358.  
  359.     DofmtCount (glob->textfmt, textfmtargs, &glob->bodyfmt, DOFMT_COUNTNEWLINES);
  360.     glob->numlines = glob->bodyfmt.numlines;
  361.     
  362.     if (!(glob->buff = (char **)AllocVec (glob->bodyfmt.bufflen
  363.                + (8 + (int)sizeof (struct IntuiText)) * glob->numlines, MEMF_PUBLIC)))
  364.         return (ReqExit (glob, FALSE));
  365.  
  366.     /* expand format string and fill in table of pointers to each line */
  367.     glob->lenptr = (ULONG *)&glob->buff[glob->numlines];
  368.     bodyitxt = (struct IntuiText *)&glob->lenptr[glob->numlines];
  369.     ptr = (char *)&bodyitxt[glob->numlines];
  370.     args = Dofmt (ptr, glob->textfmt, textfmtargs);
  371.  
  372.     if (mode == IS_EZREQUEST) gadfmtargs = args;
  373.     FillNewLineTable (glob->buff, ptr);
  374.  
  375.     /* Calculate width on screen of each line, remember largest */
  376.     for (i = 0, glob->len = 0; i < glob->numlines; i++)
  377.     {
  378.         itxt.IText = (UBYTE *)glob->buff[i];
  379.         j = glob->lenptr[i] = IntuiTextLength (&itxt);
  380.         if (j > glob->len) glob->len = j;
  381.     }
  382.     glob->width = glob->len + 70;
  383.     }
  384.     
  385.     nogadgets = (gadfmt == NULL);
  386.  
  387.     if (!nogadgets)
  388.     {
  389.     DofmtCount (gadfmt, gadfmtargs, &glob->gadfmtbuff, DOFMT_COUNTBARS);
  390.     gadlines = glob->gadfmtbuff.numlines;
  391.     glob->gadfmtbuff.bufflen += 12 * gadlines;
  392.     if (!(glob->gadstrbuff = (char **)AllocVec (glob->gadfmtbuff.bufflen, MEMF_PUBLIC)))
  393.         return (ReqExit (glob, FALSE));
  394.         
  395.     gadlenptr = (ULONG *)&glob->gadstrbuff[gadlines];
  396.     gadposptr = (ULONG *)&gadlenptr[gadlines];
  397.     ptr = (char *)&gadposptr[gadlines];
  398.     Dofmt (ptr, gadfmt, gadfmtargs);
  399.     FillBarTable (glob->gadstrbuff, ptr);
  400.  
  401.     for (i = 0; i < gadlines; i++)
  402.     {
  403.         UBYTE underscorechar = (UBYTE)underscore;
  404.         
  405.         gadlenptr[i] = myTextLength (glob->gadstrbuff[i], fontattr, &underscorechar, NULL, 0) + 24;
  406.         gadlen += gadlenptr[i];
  407.     }
  408.     
  409.     } /* if (!nogadgets) */
  410.     
  411.     /* else gadlines = 0; is always NULL (cleared at beginning) */
  412.  
  413.     if (!title)
  414.     {
  415.     if (gadlines >= 2) title = GetStr (glob->catalog, MSG_REQUEST);
  416.     else title = GetStr (glob->catalog, MSG_INFORMATION);
  417.     }
  418.     
  419.     glob->newreqwin.Title = (UBYTE *)title;
  420.  
  421.     top = (glob->scr->WBorTop + scrfontht + 1) + spacing;
  422.     val = glob->fontht + 6;
  423.  
  424.     
  425.     if (mode != IS_EZREQUEST)
  426.     {
  427. #if 1
  428.     /* AROS FIX: calc. was wrong because scr->WBorTop not taken into account. */
  429.     
  430.     height = glob->scr->WBorTop + 13 + glob->fontht * 2 + scrfontht + spacing * 3 + glob->scr->WBorBottom;
  431.     
  432. #else
  433.     height = 15 + glob->fontht * 2 + scrfontht + spacing * 3 + glob->scr->WBorBottom;
  434. #endif
  435.  
  436.     if (glob->textfmt)
  437.     {
  438.         glob->texttop = top;
  439.         glob->textht = (glob->fontht + 1) * glob->numlines + (glob->nowinbackfill ? 0 : 15);
  440.         height += spacing + glob->textht;
  441.         top += spacing + glob->textht;
  442.     }
  443.     
  444.     if (glob->minmax)
  445.     {
  446.         height += glob->fontht + spacing + 4;
  447.         if (min == 0x80000000)
  448.             DofmtArgs (glob->minmaxstr, GetStr (glob->catalog, MSG_MAX_FMT), max);
  449.         else DofmtArgs (glob->minmaxstr, (max != 0x7FFFFFFF) ?
  450.                              GetStr (glob->catalog, MSG_MIN_MAX_FMT) :
  451.                              GetStr (glob->catalog, MSG_MIN_FMT),
  452.                              min, max);
  453.         itxt.IText = glob->minmaxstr;
  454.         glob->minmaxlen = IntuiTextLength (&itxt) + 8;
  455.         if (glob->minmaxlen + 16 > glob->width) glob->width = glob->minmaxlen + 16;
  456.     }
  457.     
  458.     if (glob->width < 180) glob->width = 180;
  459.     
  460.     glob->strgadtop = top;
  461.     glob->strgadht = val;
  462.     
  463.     } /* if (mode != IS_EZREQUEST) */
  464.     else
  465.     {
  466.     glob->texttop = top;
  467.     glob->textht = (glob->fontht + 1) * glob->numlines + 15;
  468. #if 1
  469.     /* AROS FIX: Did not take scr->WBorTop into account */
  470.     height = spacing * 2 + scrfontht + glob->textht + 1 + glob->scr->WBorTop + glob->scr->WBorBottom;
  471. #else
  472.     height = spacing * 2 + scrfontht + glob->textht + 3 + glob->scr->WBorBottom;
  473. #endif
  474.     if (!nogadgets) height += spacing + val;
  475.     }
  476.  
  477.     i = gadlen + gadlines * 16;
  478.     if (i > glob->width) glob->width = i;
  479.  
  480.     if (glob->width > scrwidth) glob->width = scrwidth;
  481.     if (height > scrheight) height = scrheight;
  482.  
  483.     /* Create gadgets */
  484.     gad = (struct Gadget *)CreateContext (&glob->buttoninfo.glist);
  485.     ng.ng_VisualInfo = glob->visinfo;
  486.     ng.ng_TextAttr = fontattr;
  487.     ng.ng_TopEdge = height - spacing - val - glob->scr->WBorBottom;
  488.     ng.ng_Height = val;
  489.     ng.ng_GadgetID = 1;
  490.  
  491.     if (!nogadgets)
  492.     {
  493.     nlen = gadlenptr[gadlines-1];
  494.  
  495.     if (gadlines > 1)
  496.     {
  497.         npos = glob->width - (nlen + rightoff);
  498.         rtSpread (gadposptr, gadlenptr, gadlen,
  499.               leftoff, glob->width - rightoff, gadlines);
  500.     }
  501.     else
  502.     {
  503.         gadposptr[0] = npos = (glob->width - nlen) / 2;
  504.         retnum = 1;
  505.     }
  506.  
  507.     for (i = 0; i < gadlines; i++)
  508.     {
  509.         ng.ng_GadgetID++;
  510.         if (i == gadlines - 1) ng.ng_GadgetID = 1;
  511.         
  512.         ng.ng_LeftEdge = gadposptr[i];
  513.         ng.ng_Width = gadlenptr[i];
  514.         ng.ng_GadgetText = glob->gadstrbuff[i];
  515.         ng.ng_TextAttr = fontattr;
  516.         
  517.         if ((val = (ng.ng_GadgetID == retnum
  518.         && !(glob->reqflags & EZREQF_NORETURNKEY))))
  519.         ng.ng_TextAttr = &glob->boldattr;
  520.         
  521.         gad = my_CreateButtonGadget (gad, underscore, &ng);
  522.         
  523.         if (val) glob->retgad = gad;
  524.         if (!i) glob->yesgad = gad;
  525.     }
  526.     glob->nogad = gad;
  527.     
  528.     } /* if (!nogadgets) */
  529.     else
  530.     {
  531.     /* glob->nogad = NULL; */
  532.     npos = glob->width / 2;
  533.     nlen = 0;
  534.     }
  535.  
  536.     if (!glob->nowinbackfill && glob->texttop)
  537.     {
  538.     ng.ng_LeftEdge = leftoff;
  539.     ng.ng_TopEdge = glob->texttop;
  540.     ng.ng_Width = glob->width - (leftoff + rightoff);
  541.     ng.ng_Height = glob->textht;
  542.     ng.ng_GadgetText = NULL;
  543.     
  544.     gad = myCreateGadget (TEXT_KIND, gad, &ng, GTTX_Border, TRUE, TAG_END);
  545.     }
  546.  
  547.     glob->newreqwin.Width = glob->width;
  548.     glob->newreqwin.Height = height;
  549.     reqpos = CheckReqPos (reqpos, RTPREF_OTHERREQ, &glob->newreqwin);
  550.     
  551.     if (reqpos == REQPOS_POINTER)
  552.     {
  553.     glob->newreqwin.LeftEdge = -npos - nlen / 2;
  554.     glob->newreqwin.TopEdge = -height + glob->fontht / 2 + 5 + spacing;
  555.     }
  556.     
  557.     rtSetReqPosition (reqpos, &glob->newreqwin, glob->scr, glob->prwin);
  558.  
  559.     ng.ng_Height = glob->fontht + 6;
  560.  
  561.     if (mode != IS_EZREQUEST)
  562.     {
  563.     glob->minmaxtop = ng.ng_TopEdge = height - 2 * (glob->fontht + spacing) - 10 - glob->scr->WBorBottom;
  564.     ng.ng_GadgetText = NULL;
  565.     
  566.     if (glob->minmax)
  567.     {
  568.         ng.ng_LeftEdge = glob->minmaxleft = (glob->width - glob->minmaxlen) / 2;
  569.         ng.ng_Width = glob->minmaxlen;
  570.         ng.ng_Height -= 2;
  571.  
  572.         gad = myCreateGadget (TEXT_KIND, gad, &ng,
  573.                 GTTX_Text, glob->minmaxstr, GTTX_Border, TRUE, TAG_END);
  574.         ng.ng_Height += 2;
  575.     }
  576.     
  577.     ng.ng_LeftEdge = leftoff;
  578.     ng.ng_Width = glob->width - (leftoff + rightoff);
  579.     ng.ng_TopEdge = glob->strgadtop;
  580.     ng.ng_GadgetID = STRINGGADID;
  581.     
  582.     if (mode <= ENTER_PASSWORD)
  583.     {
  584.         stringbuff = NULL;
  585.         maxlen = 16;
  586.     }
  587.  
  588.     if (mode < ENTER_NUMBER)
  589.         gad = my_CreateStringGadget (gad, &ng, maxlen, stringbuff);
  590.     else
  591.         gad = my_CreateIntegerGadget (gad, &ng, 16, *value, GACT_STRINGCENTER);
  592.         
  593.     glob->strgad = gad;
  594.     if (gad)
  595.     {
  596.         glob->strinfo = (struct StringInfo *)glob->strgad->SpecialInfo;
  597.         glob->arg.buffer = glob->strinfo->Buffer;
  598.         
  599.         if (mode == ENTER_NUMBER && !showdef) *glob->arg.buffer = 0;
  600.         if (invisible) *(ULONG *)(glob->strinfo->Extension->Pens) = 0;
  601.     }
  602.     
  603.     /* we do this here because there seems to be a bug in GO! :-( */
  604.     gad = glob->strgad;
  605.     
  606.     } /* if (mode != IS_EZREQUEST) */
  607.  
  608.     img = &glob->headimg;
  609.     if (!glob->nowinbackfill)
  610.     {
  611.     val = glob->scr->WBorTop + glob->scr->Font->ta_YSize + 1;
  612.     img = CreateRectImage (glob, img, glob->scr->WBorLeft, val,
  613.               glob->width - glob->scr->WBorLeft - glob->scr->WBorRight,
  614.               height - val - glob->scr->WBorBottom,
  615.               SHINEPEN, BACKGROUNDPEN);
  616.               
  617.     if (glob->minmax)
  618.         img = CreateRectImage (glob, img, glob->minmaxleft, ++glob->minmaxtop,
  619.                   glob->minmaxlen, glob->fontht + 2,
  620.                   BACKGROUNDPEN, BACKGROUNDPEN);
  621.     if (glob->texttop)
  622.         img = CreateRectImage (glob, img, leftoff + 1, glob->texttop + 1,
  623.                   glob->width - (leftoff + rightoff + 2),
  624.                   glob->textht - 2, BACKGROUNDPEN, BACKGROUNDPEN);
  625.                   
  626.     if (glob->strgadtop)
  627.         img = CreateRectImage (glob, img, leftoff + 2, glob->strgadtop,
  628.                   glob->width - (leftoff + rightoff + 4), glob->strgadht,
  629.                   BACKGROUNDPEN, BACKGROUNDPEN);
  630.     }
  631.  
  632.     if (glob->textfmt)
  633.     {
  634.     /* build list of intuitexts (line by line) */
  635.     itxt.FrontPen = glob->drinfo->dri_Pens[
  636.             (glob->reqflags & GSREQF_HIGHLIGHTTEXT) ? HIGHLIGHTTEXTPEN : TEXTPEN];
  637.     itxt.TopEdge = glob->texttop + (glob->nowinbackfill ? 0 : 8);
  638.     val = (glob->width - glob->len) / 2;
  639.     for (i = 0, j = 0; i < glob->numlines; i++, j += glob->fontht + 1)
  640.     {
  641.         bodyitxt[i] = itxt;
  642.         if (glob->reqflags & EZREQF_CENTERTEXT)
  643.             val = (glob->width - glob->lenptr[i]) / 2;
  644.         if (val < 35) val = 35;
  645.         bodyitxt[i].LeftEdge = val;
  646.         bodyitxt[i].TopEdge += j;
  647.         bodyitxt[i].IText = glob->buff[i];
  648.  
  649.         if (i) bodyitxt[i-1].NextText = &bodyitxt[i];
  650.     }
  651.     
  652.     } /* if (glob->textfmt) */
  653.  
  654.     if (glob->headimg.NextImage || glob->textfmt)
  655.     {
  656.     ng.ng_LeftEdge = ng.ng_TopEdge = ng.ng_Width = ng.ng_Height = 0;
  657.     ng.ng_GadgetText = NULL;
  658.  
  659.     gad = myCreateGadget (GENERIC_KIND, gad, &ng, TAG_END);
  660.     if (gad)
  661.     {
  662.         gad->GadgetType |= GTYP_BOOLGADGET;
  663. #ifdef _AROS
  664. #warning A workaround here for AROS, because this would overpaint many gadgets
  665.         /* This seems to rely somehow on how GadTools refreshes gadgets
  666.            (the order etc.).
  667.            
  668.            This gadget is at the end of the gadget list and in GadgetRender
  669.            contains a linked list of fillrectclass images for the requester
  670.            background and textbox backgrounds. */
  671.            
  672.         gad->Flags |= GFLG_GADGHNONE;
  673. #else
  674.         gad->Flags |= GFLG_GADGIMAGE|GFLG_GADGHNONE;
  675.         gad->GadgetRender = (APTR)glob->headimg.NextImage;
  676. #endif
  677.         gad->GadgetText = &bodyitxt[0];
  678.  
  679.     }
  680.     }
  681.  
  682.     if (!gad || (!glob->nowinbackfill && !img)) return (ReqExit (glob, FALSE));
  683.  
  684.     glob->newreqwin.IDCMPFlags = glob->shareidcmp ? 0 : idcmpflags;
  685.  
  686.  
  687.     /* Now open the message window. */
  688.     if (!(glob->reqwin = OpenWindowBF (&glob->newreqwin,
  689.                            &glob->backfillhook,
  690.                        glob->drinfo->dri_Pens,
  691.                        NULL,
  692.                        NULL,
  693.                        !glob->nowinbackfill)))
  694.     return (ReqExit (glob, FALSE));
  695.  
  696.     if (glob->shareidcmp)
  697.     {
  698.     glob->reqwin->UserPort = glob->prwin->UserPort;
  699.     ModifyIDCMP (glob->reqwin, idcmpflags);
  700.     }
  701.  
  702.     AddGList (glob->reqwin, glob->buttoninfo.glist, -1, -1, NULL);
  703.     RefreshGadgets (glob->buttoninfo.glist, glob->reqwin, NULL);
  704.     GT_RefreshWindow (glob->reqwin, NULL);
  705.     glob->winlock = DoLockWindow (glob->prwin, glob->lockwindow, NULL, TRUE);
  706.     DoWaitPointer (glob->prwin, glob->waitpointer, TRUE);
  707.  
  708.     glob->frontscr = IntuitionBase->FirstScreen;
  709.     DoScreenToFront (glob->scr, glob->noscreenpop, TRUE);
  710.  
  711.     glob->buttoninfo.win = glob->reqwin;
  712.     glob->min = min;
  713.     glob->max = max;
  714.     glob->pubscr = (glob->newreqwin.Type == PUBLICSCREEN);
  715.  
  716.     /* fill in RealHandlerInfo */
  717.     glob->func = (ULONG (*)())myReqHandler;
  718.     glob->WaitMask = (1 << glob->reqwin->UserPort->mp_SigBit);
  719.     glob->DoNotWait = TRUE;
  720.  
  721.     if (reqhandler) return (CALL_HANDLER);
  722.     
  723.     return (LoopReqHandler ((struct rtHandlerInfo *)glob));
  724. }
  725.  
  726. /****************************************************************************************/
  727.  
  728. static struct Image * REGARGS CreateRectImage (Req_GlobData *glob,
  729.     struct Image *previmg, int x, int y, int w, int h, int pen, int bgpen)
  730. {
  731.     struct Image *img;
  732.  
  733.     if (!previmg) return (NULL);
  734.     
  735.     img = NewObject (NULL, "fillrectclass",
  736.              IA_Left, x, IA_Top, y,
  737.              IA_Width, w, IA_Height, h,
  738.              IA_FGPen, glob->drinfo->dri_Pens[pen],
  739.              IA_BGPen, glob->drinfo->dri_Pens[bgpen],
  740.              IA_Mode, JAM2,
  741.              (pen == SHINEPEN) ? IA_APattern : TAG_END, pattern,
  742.              IA_APatSize, 1,
  743.                    TAG_END);
  744.       
  745.     previmg->NextImage = img;
  746.     
  747.     return (img);
  748. }
  749.  
  750. /****************************************************************************************/
  751.  
  752. #define RETURN_KEY    13
  753. #define ESC_KEY        27
  754. #define SHIFT_KEY    0x60
  755. #define F1_KEY        0x50
  756. #define F10_KEY        0x59
  757.  
  758. #define QUALS_CONSIDERED    ( IEQUALIFIER_LCOMMAND | IEQUALIFIER_RCOMMAND | IEQUALIFIER_LSHIFT | \
  759.                 IEQUALIFIER_RSHIFT | IEQUALIFIER_LALT | IEQUALIFIER_RALT | \
  760.                 IEQUALIFIER_CONTROL )
  761.  
  762. /****************************************************************************************/
  763.  
  764. static ULONG ASM SAVEDS myReqHandler (
  765.     REGPARAM(a1, Req_GlobData *, glob),
  766.     REGPARAM(d0, ULONG, sigs),
  767.     REGPARAM(a0, struct TagItem *, taglist))
  768. {
  769.     struct Gadget     *tmpgad, *selgad;
  770.     struct TagItem     *tag, *tstate;
  771.     struct IntuiMessage *msg;
  772.     ULONG         class, tagdata;
  773.     UWORD         code, qual;
  774.     int         gadid, val, leftamiga, doactgad, copystr;
  775.     char         *str, key;
  776.  
  777.     /* uncomment if sigs is no longer ignored */
  778.     //if (glob->DoNotWait) sigs = 0;
  779.  
  780.     doactgad = (glob->mode != IS_EZREQUEST) && !(glob->buttoninfo.lastcode);
  781.  
  782.     /* parse tags */
  783.     tstate = taglist;
  784.     while ((tag = NextTagItem ((const struct TagItem **)&tstate)))
  785.     {
  786.     tagdata = tag->ti_Data;
  787.     if (tag->ti_Tag > RT_TagBase)
  788.     {
  789.         switch (tag->ti_Tag)
  790.         {
  791.         case RTRH_EndRequest:
  792.             glob->arg.retcode = tagdata;
  793.             return (ReqExit (glob, tagdata));
  794.         }
  795.     }
  796.     }
  797.  
  798.     while ((msg = GetWin_GT_Msg (glob->reqwin, glob->imsghook, glob->reqinfo)))
  799.     {
  800.     class = msg->Class;
  801.     code = msg->Code;
  802.     qual = msg->Qualifier;
  803.  
  804.     gadid = 0;
  805.     if (class == IDCMP_RAWKEY && glob->nogad)
  806.     {
  807.         /* Convert key to ASCII and check if a gadget pops up */
  808.         if (!(gadid = CheckGadgetKey (code, qual, &key, &glob->buttoninfo)))
  809.         {
  810.         if (!glob->buttoninfo.lastcode && !(qual & IEQUALIFIER_REPEAT))
  811.         {
  812.             leftamiga = (qual & IEQUALIFIER_LCOMMAND);
  813.             selgad = NULL;
  814.             
  815.             if (key == RETURN_KEY) selgad = glob->retgad;
  816.             if (key == ESC_KEY) selgad = glob->nogad;
  817.             
  818.             if (!(glob->reqflags & EZREQF_LAMIGAQUAL) || leftamiga)
  819.             {
  820.             switch (key)
  821.             {
  822.                 case 'V': if (!leftamiga) break;
  823.                 case 'Y': selgad = glob->yesgad; break;
  824.                 case 'B': if (!leftamiga) break;
  825.                 case 'N': case 'R': selgad = glob->nogad; break;
  826.             }
  827.             }
  828.             
  829.             if ( ( glob->fkeys ) &&
  830.              !(qual & QUALS_CONSIDERED) &&
  831.              (code >= F1_KEY) && (code <= F10_KEY) &&
  832.              (code - F1_KEY < glob->gadfmtbuff.numlines))
  833.             {
  834.             LONG    i = code - F1_KEY;
  835.  
  836.             selgad = glob->yesgad;
  837.  
  838.             while( i && selgad )
  839.             {
  840.                 selgad = selgad->NextGadget;
  841.                 --i;
  842.             }
  843.             }
  844.  
  845.             if (selgad) my_DownGadget (selgad, code, &glob->buttoninfo);
  846.             
  847.         } /* if (!glob->buttoninfo.lastcode && !(qual & IEQUALIFIER_REPEAT)) */
  848.         
  849.         } /* if (!(gadid = CheckGadgetKey (code, qual, &key, &glob->buttoninfo))) */
  850.         
  851.     } /* if (class == IDCMP_RAWKEY && glob->nogad) */
  852.         
  853.     tmpgad = (struct Gadget *)msg->IAddress;
  854.     Reply_GT_Msg (msg);
  855.     
  856.     if (class == IDCMP_REFRESHWINDOW)
  857.     {
  858.         GT_BeginRefresh (glob->reqwin);
  859.         GT_EndRefresh (glob->reqwin, TRUE);
  860.         continue;
  861.     }
  862.     
  863.     if (class == IDCMP_GADGETUP || gadid)
  864.     {
  865.         if (!gadid) gadid = tmpgad->GadgetID;
  866.         
  867.         if (gadid < STRINGGADID)
  868.         {
  869.         if (gadid == 1 || glob->mode == IS_EZREQUEST
  870.             || glob->mode == ENTER_PASSWORD)
  871.         {
  872.             glob->arg.retcode = gadid - 1;
  873.             return (ReqExit (glob, FALSE));
  874.         }
  875.         }
  876.         
  877.         if (glob->mode == IS_EZREQUEST) continue;
  878.         
  879.         if (glob->mode > ENTER_PASSWORD)
  880.         {
  881.         if (gadid == STRINGGADID)
  882.         {
  883.             if (code == 1)
  884.             {
  885.             doactgad = FALSE;
  886.             continue;
  887.             }
  888.  
  889.             my_SelectGadget ((*glob->arg.buffer || glob->allowempty)
  890.                     ? glob->yesgad : glob->nogad, glob->reqwin);
  891.             ShortDelay();
  892.         }
  893.             
  894.         if (glob->mode == ENTER_STRING)
  895.         {
  896.             copystr = (glob->arg.buffer[0] != 0);
  897.             glob->arg.retcode = copystr;
  898.             if (glob->allowempty) copystr = glob->arg.retcode = TRUE;
  899.             if (gadid > 2 && gadid < STRINGGADID) glob->arg.retcode = gadid - 1;
  900.             return (ReqExit (glob, copystr));
  901.         }
  902.         
  903.         /* glob->mode == ENTER_NUMBER */
  904.         if (glob->arg.buffer[0])
  905.         {
  906.             val = glob->strinfo->LongInt;
  907.             str = NULL;
  908.             if (val < glob->min) str = GetStr (glob->catalog, MSG_TOO_SMALL);
  909.             else if (val > glob->max) str = GetStr (glob->catalog, MSG_TOO_BIG);
  910.             if (str)
  911.             {
  912.             if (gadid == STRINGGADID)
  913.                 my_SelectGadget (glob->yesgad, glob->reqwin);
  914.             SetWinTitleFlash (glob->reqwin, str);
  915.             continue;
  916.             }
  917.             *glob->value = val;
  918.         }
  919.             
  920.         glob->arg.retcode = (glob->arg.buffer[0] != 0);
  921.         if (gadid > 2 && gadid < STRINGGADID) glob->arg.retcode = gadid - 1;
  922.         
  923.         return (ReqExit (glob, FALSE));
  924.         
  925.         } /* if (glob->mode > ENTER_PASSWORD) */
  926.             
  927.         if (gadid == STRINGGADID)
  928.         {
  929.         if (code == 1)
  930.         {
  931.             doactgad = FALSE;
  932.             continue;
  933.         }
  934.         }
  935.             
  936.         if (glob->arg.buffer[0])
  937.         {
  938.         if ((str = ((STDARGS char * (*)(long, long, struct PWCallBackArgs *))
  939.                glob->value)(glob->mode, glob->checksum, &glob->arg)))
  940.         {
  941.             /* Check if return was 'Please verify', MAJOR HACK !! */
  942.             if (*str != 'P') DisplayBeep (glob->scr);
  943.             SetWindowTitles (glob->reqwin, str, (char *)~0);
  944.             my_SetStringGadget (glob->reqwin, glob->strgad, "");
  945.         }
  946.         else return (ReqExit (glob, glob->arg.retcode));
  947.         }
  948.         
  949.     } /* if (glob->mode > ENTER_PASSWORD) */
  950.     else if (class & glob->idcmp)
  951.     {
  952.         glob->arg.retcode = glob->idcmp;
  953.         return (ReqExit (glob, FALSE));
  954.     }
  955.     
  956.     } /* while ((msg = GetWin_GT_Msg (glob->reqwin, glob->imsghook, glob->reqinfo))) */
  957.  
  958.     if (doactgad)
  959.     {
  960.         ActivateGadget (glob->strgad, glob->reqwin, NULL);
  961.     }
  962.     
  963.     glob->DoNotWait = FALSE;
  964.     
  965.     return (CALL_HANDLER);
  966. }
  967.  
  968. /****************************************************************************************/
  969.  
  970. static ULONG REGARGS ReqExit (Req_GlobData *glob, int cpystr)
  971. {
  972.     ULONG         ret = glob->arg.retcode;
  973.     struct Image     *img, *img2;
  974.  
  975.     if (cpystr && glob->mode <= ENTER_STRING)
  976.         strcpy (glob->stringbuff, glob->arg.buffer);
  977.         
  978.     DoScreenToFront (glob->frontscr, glob->noscreenpop, FALSE);
  979.     
  980.     if (glob->reqwin)
  981.     {
  982.     DoLockWindow (glob->prwin, glob->lockwindow, glob->winlock, FALSE);
  983.     DoWaitPointer (glob->prwin, glob->waitpointer, FALSE);
  984.     DoCloseWindow (glob->reqwin, glob->shareidcmp);
  985.     }
  986.     
  987.     RT_CloseCatalog (glob->catalog);
  988.     my_FreeGadgets (glob->buttoninfo.glist);
  989.     img = glob->headimg.NextImage;
  990.     
  991.     while (img)
  992.     {
  993.     img2 = img->NextImage;
  994.     DisposeObject (img);
  995.     img = img2;
  996.     }
  997.     
  998.     FreeVec (glob->buff);
  999.     FreeVec (glob->gadstrbuff);
  1000.     
  1001.     if (glob->drinfo) FreeScreenDrawInfo (glob->scr, glob->drinfo);
  1002.     
  1003.     FreeVisualInfo (glob->visinfo);
  1004.     
  1005.     if (glob->pubscr) UnlockPubScreen (NULL, glob->scr);
  1006.     if (glob->reqfont) CloseFont (glob->reqfont);
  1007.     
  1008.     FreeVec (glob);
  1009.     
  1010.     return (ret);
  1011. }
  1012.  
  1013. /****************************************************************************************/
  1014.